package main

import (
	"fmt"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"log"
	"os"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var db *gorm.DB

//sqlx 是对 sql 进行的一层封装
func initializeDatabase() (err error) {
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer（日志输出的目标，前缀和日志包含的内容——译者注）
		logger.Config{
			SlowThreshold:             time.Second, // 慢 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound（记录未找到）错误
			Colorful:                  true,        // 禁用彩色打印
		},
	)
	//data source name
	//用户名@密码@协议(ip:port)/数据库
	dsn := "root:123456@tcp(gincloud:3306)/gin_demo?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		//日志配置
		Logger: newLogger,
		//自定义表名格式
		NamingStrategy: schema.NamingStrategy{
			//自定义表名前缀
			TablePrefix: "t_",
			//单数模式(表名后不加s)
			SingularTable: true,
		},
	})
	if err != nil {
		panic(err)
	}
	return nil
}

type Student struct {
	//gorm.Model 封装了id(主键), 创建/更新时间
	gorm.Model
	Name string
	Age  uint
	Sex  bool
}

//自定义表名
func (Student) TableName() string {
	//优先级最高, 会覆盖通用配置(表名前缀/后缀...)
	return "t_udf_Student"
}

func main() {
	//连接数据库
	if err := initializeDatabase(); err != nil {
		panic(err)
	}
	fmt.Println("connected")

	// 迁移 schema(根据 Student 结构自动创建表)
	db.AutoMigrate(&Student{})

	stu := Student{
		Name: "nier",
		Age:  22,
		Sex:  false,
	}
	//插入数据
	res := db.Create(&stu)
	//获取ID
	fmt.Println("id=", stu.ID)
	//影响行数
	fmt.Println("RowsAffected=", res.RowsAffected)

	var stus = []Student{
		{Name: "gin1", Age: 23, Sex: true},
		{Name: "gin2", Age: 33, Sex: false},
		{Name: "gin3", Age: 43, Sex: true},
	}
	//通过 values 形成一条sql, 不能操作数据条数过多的情况(单条sql长度有限制)
	res2 := db.Create(&stus)
	fmt.Println("RowsAffected2=", res2.RowsAffected)

	var stus2 = []Student{
		{Name: "luffy1", Age: 18, Sex: true},
		{Name: "luffy2", Age: 28, Sex: false},
		{Name: "luffy3", Age: 38, Sex: true},
	}
	//每 100(可设置) 条记录插入一次
	res3 := db.CreateInBatches(&stus2, 100)
	fmt.Println("RowsAffected2=", res3.RowsAffected)

	//条件查询
	//单条查询
	stu5 := Student{Name: "nier"}
	res5 := db.Where(&stu5).First(&stu5)
	fmt.Println("stu5=", stu5)
	fmt.Println("RowsAffected5=", res5.RowsAffected)

	//查询多条
	var stu4 []Student
	res4 := db.Where("name = ? or name = ?", "nier", "gin1").Find(&stu4)
	fmt.Println("stu4=", stu4)
	fmt.Println("RowsAffected4=", res4.RowsAffected)

	var stus6 []Student
	db.Where([]int64{1, 3, 5}).Find(&stus6)
	for _, s := range stus6 {
		fmt.Println(s.Name)
	}

	var stu7 []Student
	res7 := db.Where("name = ?", "nier").Or("name = ?", "gin1").Find(&stu7)
	fmt.Println("stu7=", stu7)
	fmt.Println("RowsAffected4=", res7.RowsAffected)

}
